package com.tools.security.filter;

import com.tools.commons.utils.BeanUtils;
import com.tools.commons.utils.StringUtils;
import com.tools.model.entity.UserEntity;
import com.tools.config.AuthFilterWitheURLConfigure;
import com.tools.security.context.SecurityContext;
import com.tools.security.context.SecurityContextHolder;
import com.tools.security.context.UserInfo;
import com.tools.security.utils.SecurityCacheKeyUtils;
import com.tools.service.UserService;
import com.tools.commons.cache.AbstractStringCacheStore;
import com.tools.commons.constants.SystemConstants;
import com.tools.commons.exceptions.AccessTokenExpiredException;
import com.tools.commons.exceptions.GlobalException;
import com.tools.commons.response.R;
import com.tools.commons.response.Result;
import com.tools.commons.utils.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@Slf4j
@Component
@Order(1)
public class AdminAuthenticationFilter extends AbstractAuthenticationFilter {
    private static final String ADMIN_TOKEN_QUERY_NAME = "token";
    private static final String ADMIN_TOKEN_HEADER_NAME = "token";
    AbstractStringCacheStore cacheStore;
    UserService userService;

    public AdminAuthenticationFilter(AuthFilterWitheURLConfigure authConfigure,
                                     AbstractStringCacheStore cacheStore,
                                     UserService userService) {
        super(authConfigure);
        this.cacheStore = cacheStore;
        this.userService = userService;
    }

    @Override
    protected String getTokenFromRequest(HttpServletRequest request) {
        return getTokenFromRequest(request, ADMIN_TOKEN_QUERY_NAME, ADMIN_TOKEN_HEADER_NAME);
    }

    @Override
    protected boolean doAuthenticate(HttpServletRequest request, HttpServletResponse response) {
        try {
            parseToken(request);
        } catch (GlobalException exception) {
            writeToResponse(exception, response);
            return false;
        }
        return true;
    }

    private void writeToResponse(GlobalException exception, HttpServletResponse response) {
        // 由于拦截器 异常会被 包装 导致 ，会在控制台输出 错误堆栈 , 这里直接写入 response
        Result<?> result = R.fail(exception.getResponse(), exception.getArgs());
        response.setStatus(exception.getResponse().getCode());
        response.setHeader(SystemConstants.Header.CONTENT_TYPE, SystemConstants.Header.CONTENT_TYPE_JSON);
        response.setCharacterEncoding(SystemConstants.Header.UTF_8);
        try {
            PrintWriter out = response.getWriter();
            out.append(JsonUtil.obj2String(result));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void parseToken(HttpServletRequest request) {
        String token = getTokenFromRequest(request);
        log.info("parseToken token => {}", token);
        String userId = cacheStore.getAny(SecurityCacheKeyUtils.buildAccessTokenUserIdKey(token != null ? token : ""), String.class)
                .orElseThrow(AccessTokenExpiredException::new);
        UserEntity byUserId = userService.findByUserId(userId);
        UserInfo userInfo = new UserInfo();

        userInfo.setPhone(byUserId.getPhone());
        userInfo.setDoctor(byUserId.isDoctor());
        userInfo.setUserId(byUserId.getUserId());
        // if (StringUtils.equals(token, "user")) {
        //     userInfo.setUserId("user");
        //     userInfo.setPhone("18821708789");
        //     userInfo.setDoctor(false);
        // } else {
        //     userInfo.setUserId("doctor");
        //     userInfo.setPhone("18821708656");
        //     userInfo.setDoctor(true);
        // }

        SecurityContextHolder.setContext(new SecurityContext(userInfo));
    }
}

